(function($){
    //获取待上传File文件属性，用于区分同位置同名File.
    var _getFileProperty = function(file){  
        return '?t={lastModifiedDate}&l={length}'.format({
            lastModifiedDate : file['lastModifiedDate'].getTime(),
            length : file.size
        }); 
    };
    /**
     * 上传助手 
     * 构造函数.
     * uploadConfig : {
     *      xhrID : 'xhrID',
     *      url : '',
     *      files : '',
     *      formData : null,
     * }
     */    
    function _UploadHelper(uploadConfig){
        var _this = this;
        this._uploadingXHRObjs = {};    //正在上传中的XmlHttpRequest对象缓存.
        Observable.enable(this);
        this.config = uploadConfig;
    }
    /*
     * 启动ajax上传.     
     */
    _UploadHelper.prototype.startAjaxUpload = function() {
        var _this = this,
            xhrID = this.config['xhrID'] || String.newGuid(),
            formData = this.config['formData'],
            files = this.config['files'];            
        
        if (!formData) {    //若用户需要上传的是files数组，则将之转换成formData对象.
            formData = new FormData();
            if (files instanceof File) {
                var fileObj = files;
                files = [fileObj];                
            }
            for(var i=0,fileCount=files.length; i<fileCount; i++){
                var file = files[i],
                    fileName = file.name + _getFileProperty(file);    
                formData.append(fileName, file);
            }
        }
        
        _this._uploadingXHRObjs[xhrID] = $.ajax({
            type : 'post',
            timeout : 0,                            
            url : this.config['url'],                
            data : formData,
            cache : false,
            contentType : false,
            processData : false,            
            success : ujs.hr(   //上传成功后.
                function(msg) { _this.fire('success', msg); }, 
                function(msg) { _this.fire('fail', msg); }
            ),            
            error : function(xmlHttpObj, status, error) {   //上传失败或取消.                    
                if(error === 'abort'){
                    _this.fire('abort', { description : 'Cancelled' });                    
                } else {
                    _this.fire('fail', { description : 'Failed' });
                }
            },            
            complete : function(){  //请求完成后.   
                _this.fire('complete');
                delete _this._uploadingXHRObjs[xhrID];
            },            
            //自定义XMLHttpRequest对象.
            xhr : function() {  
                var xhr = new XMLHttpRequest();
                xhr.upload.addEventListener("progress", function(e) {
                    if (e.lengthComputable) {
                        _this.fire('progress', e.loaded / e.total * 100);                        
                    }
                }, false);
                return xhr;
            }
        });
        return _this._uploadingXHRObjs[xhrID];
    };
    /**
     * 终止ajax上传. 
     * 若未指定参数，则中止全部中上传.
     * @param {String} : xhrID
     */
    _UploadHelper.prototype.stopAjaxUpload = function(xhrID){
        var _this = this;
        if (xhrID){
            if(_this._uploadingXHRObjs[xhrID]){
                _this._uploadingXHRObjs[xhrID].abort();
                delete _this._uploadingXHRObjs[xhrID];
            }
        } else {
            for(xhrID in _this._uploadingXHRObjs){
                if(_this._uploadingXHRObjs.hasOwnProperty(xhrID)){
                    _this._uploadingXHRObjs[xhrID].abort();
                    delete _this._uploadingXHRObjs[xhrID];
                }
            }
        }
    };
    /**
     * 获取ajax上传相关的xhr对象. 
     * @param {String} xhrID
     */
    _UploadHelper.prototype.getAjaxUploadXHRObj = function(xhrID){
        return xhrID ? this._uploadingXHRObjs[xhrID] : this._uploadingXHRObjs;
    };
    
    //---------------------------------------------------------------------------------------------
    
    /**
     * 创建上传助手. 
     * @param {Object} uploadConfig
     */
    _UploadHelper.create = function(uploadConfig){
        return new _UploadHelper(uploadConfig);
    };
    
    //---------------------------------------------------------------------------------------------
    
    ujs.define('UploadHelper', 'ujs.browser', function(){
        return _UploadHelper;
    });     
})($);